#!/bin/sh

# EC200T 4G模块自动联网及重连脚本
# 适用于RNDIS模式的USB网络连接

# 配置信息
DEVICE="/dev/ttyUSB1"         # 模块通信串口
USB_INTERFACE="usb0"          # 模块网络接口
APN="cmnet"                   # 接入点名称
CHECK_URL="www.baidu.com"     # 网络检测URL
LOG_FILE="/var/log/4g_connect.log"  # 日志文件
RETRY_DELAY=10                # 重连尝试间隔(秒)
CHECK_INTERVAL=30             # 网络检查间隔(秒)
NTP_SERVER="ntp.aliyun.com"   # NTP服务器地址
REBOOT_DETECT_FILE="/var/run/4g_reboot_detected"  # 重启检测标志文件


# 初始化日志
echo "$(date '+%Y-%m-%d %H:%M:%S') - 脚本启动" > $LOG_FILE

# 发送AT指令到模块并获取响应
send_at_command() {
    local command=$1
    local timeout=${2:-5}  # 默认超时5秒
    
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 发送指令: $command" >> $LOG_FILE
    
    # 使用microcom发送AT指令并捕获响应
    response=$(echo -e "$command\r" | busybox microcom -t $timeout $DEVICE 2>/dev/null)
    
    # 记录响应
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 响应: $response" >> $LOG_FILE
    
    # 检查是否包含OK
    if echo "$response" | grep -q "OK"; then
        return 0
    else
        return 1
    fi
}

# 检查当前USB网络模式
check_usb_mode() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 检查当前USB网络模式..." >> $LOG_FILE
    
    if send_at_command "AT+QCFG=\"usbnet\""; then
        # 提取当前模式值
        mode=$(echo "$response" | grep "+QCFG" | awk -F': ' '{print $2}' | awk -F',' '{print $2}' | tr -d '"' | tr -d '[:space:]')
        
        if [[ "$mode" == "3" ]]; then
            echo "$(date '+%Y-%m-%d %H:%M:%S') - 当前模式: RNDIS(3)" >> $LOG_FILE
            return 0  # 已为RNDIS模式
        else
            echo "$(date '+%Y-%m-%d %H:%M:%S') - 当前模式: $mode (非RNDIS)" >> $LOG_FILE
            return 1  # 非RNDIS模式
        fi
    fi
    
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 检查USB网络模式失败，默认尝试设置RNDIS模式" >> $LOG_FILE
    return 1  # 假设非RNDIS模式
}

# 配置模块为RNDIS模式
configure_rndis_mode() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 开始配置RNDIS模式..." >> $LOG_FILE
    
    # 设置USB网络模式为RNDIS(3)
    if ! send_at_command "AT+QCFG=\"usbnet\",3"; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') - 设置RNDIS模式失败" >> $LOG_FILE
        return 1
    fi
    
    # 重启模块使配置生效
    if ! send_at_command "AT+CFUN=1,1"; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') - 重启模块失败" >> $LOG_FILE
        return 1
    fi
    
    # 等待模块重启
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 等待模块重启(30秒)..." >> $LOG_FILE
    sleep 30
    
    echo "$(date '+%Y-%m-%d %H:%M:%S') - RNDIS模式配置完成" >> $LOG_FILE
    return 0
}

# 检查SIM卡状态
check_sim_status() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 检查SIM卡状态..." >> $LOG_FILE
    
    # 最多尝试3次
    for i in 1 2 3;
    do
        if send_at_command "AT+CPIN?"; then
            if echo "$response" | grep -q "+CPIN: READY"; then
                echo "$(date '+%Y-%m-%d %H:%M:%S') - SIM卡就绪" >> $LOG_FILE
                return 0
            else
                echo "$(date '+%Y-%m-%d %H:%M:%S') - SIM卡未就绪: $response" >> $LOG_FILE
            fi
        fi
        sleep 2
    done
    
    echo "$(date '+%Y-%m-%d %H:%M:%S') - SIM卡检查失败" >> $LOG_FILE
    return 1
}

# 检查信号强度
check_signal_strength() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 检查信号强度..." >> $LOG_FILE
    
    if send_at_command "AT+CSQ"; then
        # 提取信号强度值
        csq=$(echo "$response" | grep "+CSQ" | awk -F': ' '{print $2}' | awk -F',' '{print $1}')
        
        if [[ -n "$csq" && "$csq" != "99" && "$csq" -ge 10 ]]; then
            echo "$(date '+%Y-%m-%d %H:%M:%S') - 信号强度良好: $csq" >> $LOG_FILE
            return 0
        else
            echo "$(date '+%Y-%m-%d %H:%M:%S') - 信号强度不足: $csq" >> $LOG_FILE
            return 1
        fi
    fi
    
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 信号强度检查失败" >> $LOG_FILE
    return 1
}

# 设置APN
set_apn() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 设置APN..." >> $LOG_FILE
    
    if ! send_at_command "AT+QICSGP=1,1,\"$APN\""; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') - 设置APN失败" >> $LOG_FILE
        return 1
    fi
    
    echo "$(date '+%Y-%m-%d %H:%M:%S') - APN设置成功: $APN" >> $LOG_FILE
    return 0
}

# 检查网络注册状态
check_network_registration() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 检查网络注册状态..." >> $LOG_FILE
    
    if send_at_command "AT+COPS?"; then
        # 检查响应中是否包含网络运营商信息
        if echo "$response" | grep -q "CHINA MOBILE\|CHINA UNICOM\|CHINA TELECOM"; then
            echo "$(date '+%Y-%m-%d %H:%M:%S') - 已注册到网络" >> $LOG_FILE
            return 0
        else
            echo "$(date '+%Y-%m-%d %H:%M:%S') - 未注册到网络" >> $LOG_FILE
            return 1
        fi
    fi
    
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 检查网络注册状态失败" >> $LOG_FILE
    return 1
}

# 设置数据呼叫
setup_data_call() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 设置数据呼叫..." >> $LOG_FILE
    
    if ! send_at_command "AT+QNETDEVCTL=1,1,1" 10; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') - 设置数据呼叫失败" >> $LOG_FILE
        return 1
    fi
    
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 数据呼叫设置成功" >> $LOG_FILE
    return 0
}

# 获取IP地址
get_ip_address() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 获取IP地址..." >> $LOG_FILE
    
    # 停止任何现有的DHCP客户端
    pkill -f "udhcpc.*$USB_INTERFACE" 2>/dev/null
    sleep 2
    
    # 启动DHCP客户端获取IP
    dhcp_output=$(busybox udhcpc -fnq -i $USB_INTERFACE 2>&1)
    echo "$(date '+%Y-%m-%d %H:%M:%S') - DHCP输出: $dhcp_output" >> $LOG_FILE
    
    # 检查是否成功获取IP
    if echo "$dhcp_output" | grep -q "lease of"; then
        ip=$(echo "$dhcp_output" | grep "lease of" | awk '{print $3}')
        echo "$(date '+%Y-%m-%d %H:%M:%S') - 获取IP成功: $ip" >> $LOG_FILE
        return 0
    else
        echo "$(date '+%Y-%m-%d %H:%M:%S') - 获取IP失败" >> $LOG_FILE
        return 1
    fi
}

# 检查网络连接
check_network() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 检查网络连接..." >> $LOG_FILE
    
    # 检查接口是否有IP地址
    ip_addr=$(ip -4 addr show $USB_INTERFACE | grep inet | awk '{print $2}' | cut -d/ -f1)
    
    if [[ -z "$ip_addr" ]]; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') - 接口 $USB_INTERFACE 没有IP地址" >> $LOG_FILE
        return 1
    fi
    
    # 尝试ping测试
    if ping -c 3 -I $USB_INTERFACE $CHECK_URL >/dev/null 2>&1; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') - 网络连接正常" >> $LOG_FILE
        return 0
    else
        echo "$(date '+%Y-%m-%d %H:%M:%S') - 网络连接失败" >> $LOG_FILE
        return 1
    fi
}

# 检查是否为重启后首次运行
check_reboot() {
    if [ ! -f "$REBOOT_DETECT_FILE" ]; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') - 检测到系统重启，将在联网后进行时间同步" >> "$LOG_FILE"
        touch "$REBOOT_DETECT_FILE"
        return 0  # 是重启后首次运行
    else
        return 1  # 不是重启后首次运行
    fi
}

# 强制使用ntpdate更新系统时间（仅在重启后调用）
update_system_time_after_reboot() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 开始使用ntpdate更新系统时间..." >> "$LOG_FILE"
    
    # 检查ntpdate是否存在
    if ! command -v ntpdate >/dev/null 2>&1; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') - 错误: 未找到ntpdate命令，请确保已安装" >> "$LOG_FILE"
        return 1
    fi
    
    # 尝试更新系统时间（最多3次）
    local attempt=1
    while [ "$attempt" -le 3 ]; do
        echo "$(date '+%Y-%m-%d %H:%M:%S') - 尝试 $attempt/3: ntpdate -u $NTP_SERVER" >> "$LOG_FILE"
        
        if ntpdate -u "$NTP_SERVER" >/dev/null 2>&1; then
            echo "$(date '+%Y-%m-%d %H:%M:%S') - 系统时间更新成功" >> "$LOG_FILE"
            echo -e "\033[32m$(date '+%Y-%m-%d %H:%M:%S') - 系统时间已通过NTP同步\033[0m"
            return 0
        else
            echo "$(date '+%Y-%m-%d %H:%M:%S') - 尝试 $attempt/3 失败" >> "$LOG_FILE"
            sleep 2
            attempt=$((attempt + 1))
        fi
    done
    
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 错误: 所有ntpdate尝试均失败" >> "$LOG_FILE"
    return 1
}

# 连接网络
connect_network() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 开始连接网络..." >> $LOG_FILE
    
    # 检查当前USB模式
    if ! check_usb_mode; then
        # 非RNDIS模式，需要配置
        if ! configure_rndis_mode; then
            return 1
        fi
    else
        echo "$(date '+%Y-%m-%d %H:%M:%S') - 模块已处于RNDIS模式，跳过模式配置" >> $LOG_FILE
    fi
    
    # 检查SIM卡状态
    if ! check_sim_status; then
        return 1
    fi
    
    # 检查信号强度
    if ! check_signal_strength; then
        return 1
    fi
    
    # 设置APN 
    if ! set_apn; then
        return 1
    fi
    
    # 检查网络注册状态 
    if ! check_network_registration; then
        return 1
    fi
    
    # 设置数据呼叫
    if ! setup_data_call; then
        return 1
    fi
    
    # 获取IP地址
    if ! get_ip_address; then
        return 1
    fi
    
    # 终端输出连接完成消息
    echo -e "\033[32m$(date '+%Y-%m-%d %H:%M:%S') - 网络连接成功！\033[0m"
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 网络连接成功" >> "$LOG_FILE"
    
    # 只有在重启后才进行时间同步
    if check_reboot; then
        update_system_time_after_reboot
        hwclock -w #同步硬件时间
    fi
    
    return 0
}

# 主循环
main() {
   # 删除重启检测标志文件（确保每次重启后都会检测）
    rm -f "$REBOOT_DETECT_FILE"
    # 初始连接尝试
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 开始初始连接..." >> $LOG_FILE
    if ! connect_network; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') - 初始连接失败，将重试" >> $LOG_FILE
    fi
    # 监控网络连接
    while true; 
    do
        if check_network; then
            # 网络正常，等待下次检查
            sleep $CHECK_INTERVAL
        else
            # 网络断开，尝试重连
            echo "$(date '+%Y-%m-%d %H:%M:%S') - 检测到网络断开，尝试重连..." >> $LOG_FILE
            
            # 尝试重连最多3次
            for i in 1 2 3; 
            do
                echo "$(date '+%Y-%m-%d %H:%M:%S') - 重连尝试 $i/3" >> $LOG_FILE
                
                # 先尝试简单的重连方法(获取新IP)
                if get_ip_address; then
                    if check_network; then
                        echo "$(date '+%Y-%m-%d %H:%M:%S') - 重连成功" >> $LOG_FILE
                        break
                    fi
                fi
                
                # 如果简单重连失败，进行完整的连接过程
                if [[ "$i" -lt 3 ]]; then
                    echo "$(date '+%Y-%m-%d %H:%M:%S') - 尝试完整重连过程..." >> $LOG_FILE
                    if connect_network; then
                        break
                    fi
                fi
                
                echo "$(date '+%Y-%m-%d %H:%M:%S') - 重连尝试 $i/3 失败，等待 $RETRY_DELAY 秒后重试" >> $LOG_FILE
                sleep $RETRY_DELAY
            done
            
            # 如果所有重试都失败
            if [[ "$i" -eq 3 ]]; then
                echo "$(date '+%Y-%m-%d %H:%M:%S') - 所有重连尝试失败，等待 $CHECK_INTERVAL 秒后再次检查" >> $LOG_FILE
            fi
            
            sleep $CHECK_INTERVAL
        fi
    done
}

# 启动主程序
main    